package ProxyDemo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * new ProxyInstance()提供一个代理人对象：小王
 * 
 * @author jie
 * TODO Proxy.newProxyInstance(originObj.getClass().getClassLoader(),
 * 				originObj.getClass().getInterfaces(), new ProxyManer(daiLiRen));
 * 	代理类，
 *  都实现 接口InvocationHandler,调用接口，会执重定向到ProxyManer#invoke 函数（可以进行代理工作了）
 *  前后增加 listener
 *
 */

public class TestDynamicProxy {

	public static void main(String[] args) {
//		XiaLuo originObj = new XiaLuo();
		YuanHua originObj = new YuanHua();
		// 找代理公司
		// 参数1：代理人和委托人 必须具有同样的 类加载器
		// 参数2：代理人和委托人必须具有同样的 接口
		// 参数3：代理人必须经过专业的培训
		// Proxy.newProxyInstance(loader, interfaces, h);
		// Object newProxyInstance =
		// Proxy.newProxyInstance(xiaLuo.getClass().getClassLoader(),
		// 强转为夏洛需要实现的接口
		SendS ss = (SendS) Proxy.newProxyInstance(originObj.getClass().getClassLoader(),
				originObj.getClass().getInterfaces(), new ProxyManer(originObj));
//		ss.sendFlower();// 传递方法名 给invoke方法
		// 替换对象 
		ss.buyHouse();
	}
}

// 代理公司员工，具备专业的培训
class ProxyManer implements InvocationHandler {
	SendS sendS;

	public ProxyManer(SendS s) {
		// 传递委托人
		// 才有方法和参数
		sendS = s;
	}

	/**
	 * @param proxy 委托人
	 * @param method 委托人 让你代理的工作（代理方法）
	 * @param args 代理工作的参数(代理方法的参数
	 * @Object 返回值：代理工作的返回值
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// method.invoke(obj, args);
		System.out.println("invoke..开始代理工作 加入 监听。。。或者修改 参数。。。");
//		 Object invoke = method.invoke(proxy, args);//bug throw Exception
		Object invoke = method.invoke(sendS, args);
//		Object invoke = method.invoke(new XiaLuo(), args);// 可以替换为其他人。
		System.out.println("结束代理工作 监听 结果。。。");
		return invoke;
	}
}

interface SendS {
	void sendFlower();
	void buyHouse();
}

class XiaLuo implements SendS {

	public void sendFlower() {
		System.out.println("夏洛 送花 给  秋雅");
	}

	public void buyHouse() {
		System.out.println("夏洛 送 🏠 给  秋雅");
	}

}

class YuanHua implements SendS {

	public void sendFlower() {
		System.out.println("元华 送 Flower");
	}

	public void buyHouse() {
		System.out.println("元华 送 房");
	}

}
